<?php
namespace SunAdmin\Service;

use think\facade\Cache;
use think\facade\Db;
use Redis;

class SystemInfoService
{
    public function getSystemMetrics(): array
    {
        try {
            // PHP 版本
            $phpVersion = PHP_VERSION;

            // Swoole 版本
            $swooleVersion = defined('SWOOLE_VERSION') ? SWOOLE_VERSION : '未加载';

            // 操作系统版本
            $osVersion = php_uname('s') . ' ' . php_uname('r');

            // CPU核心数
            $cpuCores = 'N/A';
            try {
                if (function_exists('swoole_cpu_num')) {
                    $cpuCores = swoole_cpu_num();
                } elseif (is_readable('/proc/cpuinfo')) {
                    $cpuinfo = @file_get_contents('/proc/cpuinfo');
                    if ($cpuinfo && preg_match_all('/^processor/m', $cpuinfo, $matches)) {
                        $cpuCores = count($matches[0]);
                    }
                } elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                    // Windows环境下的shell命令，增加超时保护
                    $output = $this->safeShellExec('wmic cpu get NumberOfLogicalProcessors /format:list', 5);
                    if ($output && preg_match('/NumberOfLogicalProcessors=(\d+)/', $output, $matches)) {
                        $cpuCores = $matches[1];
                    }
                }
            } catch (\Throwable $e) {
                trace('[SystemInfoService] 获取CPU核心数失败: ' . $e->getMessage(), 'warning');
            }

            // CPU使用率（近似，1分钟负载/核心数*100%）
            $cpuUsage = 'N/A';
            try {
                if (function_exists('sys_getloadavg') && is_numeric($cpuCores) && $cpuCores > 0) {
                    $load = sys_getloadavg();
                    if ($load && isset($load[0])) {
                        $cpuUsage = round($load[0] / $cpuCores * 100, 1);
                        if ($cpuUsage > 100) $cpuUsage = 100;
                    }
                }
            } catch (\Throwable $e) {
                trace('[SystemInfoService] 获取CPU使用率失败: ' . $e->getMessage(), 'warning');
            }

            // 内存总量/使用率
            $memoryTotal = 'N/A';
            $memoryUsage = 'N/A';
            try {
                if (is_readable('/proc/meminfo')) {
                    $meminfo = @file_get_contents('/proc/meminfo');
                    if ($meminfo && preg_match('/MemTotal:\s+(\d+) kB/', $meminfo, $total) && 
                        preg_match('/MemAvailable:\s+(\d+) kB/', $meminfo, $avail)) {
                        $memoryTotal = round($total[1] / 1024 / 1024, 2) . ' GB';
                        $used = $total[1] - $avail[1];
                        $memoryUsage = round($used / $total[1] * 100, 1);
                    }
                } elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                    $output = $this->safeShellExec('wmic computersystem get TotalPhysicalMemory', 5);
                    if ($output && preg_match('/\d+/', $output, $matches)) {
                        $memoryTotal = round($matches[0] / 1024 / 1024 / 1024, 2) . ' GB';
                    }
                    $output = $this->safeShellExec('wmic OS get FreePhysicalMemory,TotalVisibleMemorySize /Value', 5);
                    if ($output && preg_match_all('/(\w+)=(\d+)/', $output, $matches)) {
                        $vals = array_combine($matches[1], $matches[2]);
                        if (isset($vals['FreePhysicalMemory'], $vals['TotalVisibleMemorySize'])) {
                            $used = $vals['TotalVisibleMemorySize'] - $vals['FreePhysicalMemory'];
                            $memoryUsage = round($used / $vals['TotalVisibleMemorySize'] * 100, 1);
                        }
                    }
                }
            } catch (\Throwable $e) {
                trace('[SystemInfoService] 获取内存信息失败: ' . $e->getMessage(), 'warning');
            }

            // 服务器运行时间
            $serverUptime = 'N/A';
            try {
                if (is_readable('/proc/uptime')) {
                    $uptime = @file_get_contents('/proc/uptime');
                    if ($uptime) {
                        $secs = (int)floatval(explode(' ', $uptime)[0]);
                        $days = floor($secs / 86400);
                        $hours = floor(($secs % 86400) / 3600);
                        $minutes = floor(($secs % 3600) / 60);
                        $serverUptime = "{$days}天{$hours}小时{$minutes}分钟";
                    }
                } elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                    $output = $this->safeShellExec('net stats srv', 5);
                    if ($output && preg_match('/统计自(.*)/u', $output, $matches)) {
                        $serverUptime = trim($matches[1]);
                    }
                }
            } catch (\Throwable $e) {
                trace('[SystemInfoService] 获取服务器运行时间失败: ' . $e->getMessage(), 'warning');
            }

            // MySQL 版本
            $mysqlVersion = 'N/A';
            try {
                $result = Db::query('SELECT VERSION() as v');
                $mysqlVersion = $result[0]['v'] ?? 'N/A';
            } catch (\Throwable $e) {
                trace('[SystemInfoService] 获取MySQL版本失败: ' . $e->getMessage(), 'warning');
            }

            // Redis 版本
            $redisVersion = 'N/A';
            try {
                $redis = Cache::store('redis')->handler();
                $info = $redis->info();
                $redisVersion = $info['redis_version'] ?? 'N/A';
                $redis->close();
            } catch (\Throwable $e) {
                trace('[SystemInfoService] 获取Redis版本失败: ' . $e->getMessage(), 'warning');
            }

            // SunAdmin 版本
            $sunAdminVersion = '1.0.0';

            return [
                'cpu_cores' => $cpuCores,
                'cpu_usage' => $cpuUsage,
                'memory_total' => $memoryTotal,
                'memory_usage' => $memoryUsage,
                'os_version' => $osVersion,
                'server_uptime' => $serverUptime,
                'php_version' => $phpVersion,
                'swoole_version' => $swooleVersion,
                'mysql_version' => $mysqlVersion,
                'redis_version' => $redisVersion,
                'sun_admin_version' => $sunAdminVersion,
            ];
        } catch (\Throwable $e) {
            trace('[SystemInfoService] getSystemMetrics执行异常: ' . $e->getMessage(), 'error');
            // 返回默认值，避免整个方法失败
            return [
                'cpu_cores' => 'N/A',
                'cpu_usage' => 'N/A',
                'memory_total' => 'N/A',
                'memory_usage' => 'N/A',
                'os_version' => php_uname('s') . ' ' . php_uname('r'),
                'server_uptime' => 'N/A',
                'php_version' => PHP_VERSION,
                'swoole_version' => defined('SWOOLE_VERSION') ? SWOOLE_VERSION : '未加载',
                'mysql_version' => 'N/A',
                'redis_version' => 'N/A',
                'sun_admin_version' => '1.0.0',
            ];
        }
    }
    
    /**
     * 安全执行shell命令，带超时控制
     * @param string $command 要执行的命令
     * @param int $timeout 超时时间（秒）
     * @return string|false
     */
    private function safeShellExec(string $command, int $timeout = 5)
    {
        try {
            // 在命令前添加超时控制
            if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                // Windows下使用timeout命令
                $command = "timeout /t {$timeout} " . $command;
            } else {
                // Linux/Unix下使用timeout命令
                $command = "timeout {$timeout} " . $command;
            }
            
            $result = @shell_exec($command);
            return $result !== null ? $result : false;
        } catch (\Throwable $e) {
            trace('[SystemInfoService] shell命令执行失败: ' . $e->getMessage(), 'warning');
            return false;
        }
    }
} 